package com.fengxing.ams.web.facade;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.Set;

import org.apache.commons.codec.binary.Base64;
import org.apache.commons.configuration.Configuration;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpException;
import org.jsoup.Jsoup;
import org.jsoup.helper.StringUtil;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Direction;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import com.fengxing.ams.pub.AMSException;
import com.fengxing.ams.pub.constants.ReltCode;
import com.fengxing.ams.pub.constants.ResourceType;
import com.fengxing.ams.pub.constants.SystemParam;
import com.fengxing.ams.pub.persistence.DynamicSpecifications;
import com.fengxing.ams.pub.persistence.SearchFilter;
import com.fengxing.ams.pub.persistence.SearchFilter.Operator;
import com.fengxing.ams.pub.util.AESUtil;
import com.fengxing.ams.pub.util.ConvertUtil;
import com.fengxing.ams.pub.util.MD5Util;
import com.fengxing.ams.pub.util.NumSequenceUtil;
import com.fengxing.ams.pub.util.ResourceUtil;
import com.fengxing.ams.web.common.IContextManager;
import com.fengxing.ams.web.facade.intf.IAccountFacade;
import com.fengxing.ams.web.facade.intf.IUserFacade;
import com.fengxing.ams.web.facade.mouble.batchline.BatchLineVO;
import com.fengxing.ams.web.facade.mouble.batchline.IBatchLineDAO;
import com.fengxing.ams.web.facade.mouble.college.CollegeVO;
import com.fengxing.ams.web.facade.mouble.college.ICollegeDAO;
import com.fengxing.ams.web.facade.mouble.luqu.EntityScoreVO;
import com.fengxing.ams.web.facade.mouble.luqu.ILuQuDAO;
import com.fengxing.ams.web.facade.mouble.luqu.IMajorDAO;
import com.fengxing.ams.web.facade.mouble.luqu.IMajorEnrollDAO;
import com.fengxing.ams.web.facade.mouble.luqu.LuQuVO;
import com.fengxing.ams.web.facade.mouble.luqu.MajorEnrollVO;
import com.fengxing.ams.web.facade.mouble.luqu.MajorVO;
import com.fengxing.ams.web.facade.mouble.luqu.ParamVO;
import com.fengxing.ams.web.facade.mouble.realtime.IRealtimeStudentDAO;
import com.fengxing.ams.web.facade.mouble.realtime.ISchool2DAO;
import com.fengxing.ams.web.facade.mouble.realtime.MajorVO2;
import com.fengxing.ams.web.facade.mouble.realtime.RealtimeStudentVO;
import com.fengxing.ams.web.facade.mouble.realtime.SchoolVO2;
import com.fengxing.ams.web.facade.mouble.resource.IUserResourceDAO;
import com.fengxing.ams.web.facade.mouble.resource.UserResourceVO;
import com.fengxing.ams.web.facade.mouble.score.IScoreDAO;
import com.fengxing.ams.web.facade.mouble.score.ScoreVO;
import com.fengxing.ams.web.facade.mouble.timu.DaAnVO;
import com.fengxing.ams.web.facade.mouble.timu.IDaAnDAO;
import com.fengxing.ams.web.facade.mouble.timu.ITiMuDAO;
import com.fengxing.ams.web.facade.mouble.timu.TiMuVO;
import com.fengxing.ams.web.facade.mouble.user.IMenuDao;
import com.fengxing.ams.web.facade.mouble.user.IResetTokenDAO;
import com.fengxing.ams.web.facade.mouble.user.IRoleDAO;
import com.fengxing.ams.web.facade.mouble.user.IUserDAO;
import com.fengxing.ams.web.facade.mouble.user.MenuVO;
import com.fengxing.ams.web.facade.mouble.user.ResetTokenVO;
import com.fengxing.ams.web.facade.mouble.user.UserVO;
import com.fengxing.ams.web.security.utils.PasswordUtil;
import com.fengxing.ams.web.security.utils.PrincipalUtil;

@Component
@Transactional
public class UserFacade extends BaseFacade implements IUserFacade {
	@Autowired
	private IUserDAO userDAO;

	@Autowired
	private IRoleDAO roleDAO;

	@Autowired
	private ILuQuDAO luQuDAO;

	@Autowired
	private IAccountFacade accountFacade;

	@Autowired
	private IBatchLineDAO batchLineDAO;

	@Autowired
	private ITiMuDAO tiMuDAO;
	
	@Autowired
	private IDaAnDAO daAnDAO;
	
	@Autowired
	private ICollegeDAO collegeDAO;
	
	@Autowired
	private IMajorDAO majorDAO;
	
	@Autowired
	private IUserResourceDAO userResourceDAO;
	@Autowired
	private IResetTokenDAO resetTokenDAO;
	@Autowired
	private IContextManager contextManager;
	@Autowired
	private IMenuDao menuDao;

	@Transactional(readOnly = true)
	public UserVO login(UserVO param) {
		UserVO userVO = this.userDAO.findByEmail(param.getEmail());
		if (userVO == null) {
			throw new AMSException("email.password.not.corrent");
		}
		if (!userVO.getPassword().equals(MD5Util.md5(param.getPassword()+param.getEmail()))) {
			throw new AMSException("email.password.not.corrent");
		}
		// token字符串
		String tokenStr = "";
		// auth_info = uid + “|” + tel + “|” + login_time + “|” + expire_time +
		// “|” + rnd_string

		tokenStr += userVO.getUserId()
				+ "|"
				+ userVO.getEmail()
				+ "|"
				+ System.currentTimeMillis()
				+ "|"
				+ (System.currentTimeMillis()) + "|";

		// 随机字符串
		String rndStr = "";
		for (int i = 0; i < 8; i++) {
			rndStr += (char) (Math.random() * 58 + 'A');
		}
		// 得到auth_info
		tokenStr += rndStr;
		// 从数据库得到密钥
		byte[] temp1 = Base64
				.encodeBase64(AESUtil.aesEncode(
						this.configManager.getProperty(SystemParam.AUTH_KEY, ""),
						tokenStr));
		try {
			String finalTokenStr = userVO.getUserId() + "|"
					+ new String(temp1, "UTF-8");
			temp1 = Base64.encodeBase64(finalTokenStr.getBytes("UTF-8"));
		} catch (Exception e) {
			throw new AMSException("Token加密错误", e);
		}
		try {
			userVO.setSubject(new String(temp1, "UTF-8"));
		} catch (UnsupportedEncodingException e) {
		}
		this.contextManager.createSession(userVO);
		return userVO;
	}

	@Transactional(readOnly = false)
	public void updateUserLoginInfo(Long id) {
		accountFacade.updateUserLoginInfo(id);
	}

	@Transactional(readOnly = false)
	public void saveUser(UserVO user) {
		this.userDAO.save(user);
	}

	@Transactional(readOnly = true)
	public UserVO findUserById(Long id) {
		return this.userDAO.findOne(id);
	}

	@Transactional(readOnly = false)
	public void updateUser(UserVO user) {
		this.userDAO.save(user);
	}

	@Transactional(readOnly = false)
	public void deleteById(Long l) {
		this.userDAO.delete(l);
	}
	
	@Transactional(readOnly = false)
	public void updateUserInfoProfile(UserVO userVO) {
		this.userDAO.updateLoginInfoProfile(userVO.getUserId(), userVO.getName(), userVO.getGendar(), userVO.getScore(), userVO.getSubject(), userVO.getUpdate_date());
	}

	@Transactional(readOnly = false)
	public UserVO signUp(UserVO userVO) {
		userVO.setName(userVO.getEmail());
		long defaultRoleId = ConvertUtil.toLong(
				configManager.getProperty("default_role", "1"), 1L);
		userVO.getRoleList().add(roleDAO.findOne(defaultRoleId));
		
		//新增免费资源
		UserResourceVO one = new UserResourceVO();
		one.setUserVO(userVO);
		one.setTime(3);
		one.setType(ResourceType.ENROLL_PLAN);
		UserResourceVO two = new UserResourceVO();
		two.setUserVO(userVO);
		two.setTime(3);
		two.setType(ResourceType.ENROLLMENT);
		UserResourceVO three = new UserResourceVO();
		three.setUserVO(userVO);
		three.setTime(3);
		three.setType(ResourceType.SOLUTION);
		List<UserResourceVO> list = new ArrayList<UserResourceVO> ();
		list.add(one);
		list.add(two);
		list.add(three);
//		userVO.setUserResourceList(list);
		UserVO user = this.userDAO.save(userVO);
		return user;
	}

	@Transactional(readOnly = true)
	public UserVO userLogin(UserVO param) {
		UserVO userVO = this.userDAO.findByEmail(param.getEmail());
		if (userVO == null) {
			throw new AMSException(ReltCode.NO_ACCOUNT);
		}

		if (!PasswordUtil.validPassword(param.getPassword(),
				userVO.getPassword())) {
			throw new AMSException(ReltCode.NO_ACCOUNT);
		}
		return userVO;
	}

	@Override
	public Page<UserVO> getUserInfos(Collection<UserVO> users, Pageable pageable) {
		List<Long> userIds = new ArrayList<Long>();
		for (UserVO user : users) {
			userIds.add(user.getUserId());
		}
		return userDAO.findAllByUserIdIn(userIds, pageable);
	}

	@Override
	public Page<UserVO> getUserInfo(UserVO user, Pageable pageable) {
		List<SearchFilter> searchFilterList = new ArrayList<SearchFilter>();
		if (null != user.getUserId()) {
			SearchFilter filter = new SearchFilter("userId", Operator.EQ,
					user.getUserId(), null);
			searchFilterList.add(filter);
		}
		if (StringUtils.isNotBlank(user.getName())) {
			SearchFilter filter = new SearchFilter("name", Operator.LIKE,
					user.getName(), null);
			searchFilterList.add(filter);
		}
		if (StringUtils.isNotBlank(user.getEmail())) {
			SearchFilter filter = new SearchFilter("email", Operator.EQ,
					user.getEmail(), null);
			searchFilterList.add(filter);
		}
		if (StringUtils.isNotBlank(user.getMobile())) {
			SearchFilter filter = new SearchFilter("mobile", Operator.EQ,
					user.getMobile(), null);
			searchFilterList.add(filter);
		}
		if (null != user.getStatus()) {
			SearchFilter filter = new SearchFilter("status", Operator.EQ,
					user.getStatus(), null);
			searchFilterList.add(filter);
		}
		SearchFilter userFilter1 = new SearchFilter("userId", Operator.GT, 100,
				null);
		searchFilterList.add(userFilter1);

		SearchFilter userFilter2 = new SearchFilter("userId", Operator.NEQ,
				PrincipalUtil.getCurrentUserId(), null);
		searchFilterList.add(userFilter2);
		Page<UserVO> users = this.userDAO.findAll(DynamicSpecifications
				.bySearchFilter(searchFilterList, UserVO.class), pageable);
		return users;
	}

	private UserVO getUser(String username, String email) {
		List<SearchFilter> searchFilterList = new ArrayList<SearchFilter>();
		if (StringUtils.isNotBlank(username)) {
			SearchFilter filter = new SearchFilter("name", Operator.EQ,
					username, null);
			searchFilterList.add(filter);
		}
		if (StringUtils.isNotBlank(email)) {
			SearchFilter filter = new SearchFilter("email", Operator.EQ, email,
					null);
			searchFilterList.add(filter);
		}
		return userDAO.findOne(DynamicSpecifications.bySearchFilter(
				searchFilterList, UserVO.class));
	}

	@Override
	public UserVO findUserByEmail(String email) {
		return userDAO.findByEmail(email);
	}

	@Override
	public void updateUserInfo(UserVO userVO) {
		userDAO.updateUserDetail(userVO.getUserId(), userVO.getName(),
				userVO.getPhoto(), userVO.getMobile());
	}

	private String generatePassword(String chars, int lengt) {
		if (chars == null) {
			chars = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
		}
		String password = "";
		Random random = new Random();
		for (int i = 0; i < lengt; i++) {
			password += chars.charAt(random.nextInt(chars.length() - 1));
		}
		return password;
	}

	@Override
	public UserVO findOneById(Long id) {
		return userDAO.findOne(id);
	}

	@Transactional(readOnly = true)
	public List<LuQuVO> getLuQuInfo(ParamVO paramVO, Integer year) {
		List<SearchFilter> searchFilterList = new ArrayList<SearchFilter>();
		String batch = paramVO.getBatch();
		String enroll = paramVO.getEnroll();
		String major = paramVO.getMajor();
		String plan = paramVO.getPlan();
		String region = paramVO.getRegion();
		String school = paramVO.getSchool();
		String type = paramVO.getType();

		SearchFilter filter = null;

		filter = new SearchFilter("zongfen", Operator.BETWEEN,
				paramVO.getMinScore(), paramVO.getMaxScore());
		searchFilterList.add(filter);

		if (year != null) {
			filter = new SearchFilter("year", Operator.EQ, year, null);
			searchFilterList.add(filter);
		}

		filter = new SearchFilter("type", Operator.EQ, type, null);
		searchFilterList.add(filter);

		if (StringUtils.isNotBlank(batch)) {
			filter = new SearchFilter("batch", Operator.EQ, batch, null);
			searchFilterList.add(filter);
		}

		if (StringUtils.isNotBlank(plan)) {
			filter = new SearchFilter("plan", Operator.EQ, plan, null);
			searchFilterList.add(filter);
		}

		if (StringUtils.isNotBlank(enroll)) {
			filter = new SearchFilter("enroll", Operator.EQ, enroll, null);
			searchFilterList.add(filter);
		}

		if (StringUtils.isNotBlank(school)) {
			filter = new SearchFilter("school", Operator.LIKE,
					'%' + school + '%', null);
			searchFilterList.add(filter);
		}

		if (StringUtils.isNotBlank(major)) {
			filter = new SearchFilter("major", Operator.LIKE,
					'%' + major + '%', null);
			searchFilterList.add(filter);
		}
		Specification<LuQuVO> spec = DynamicSpecifications.bySearchFilter(
				searchFilterList, LuQuVO.class);
		Sort s=new Sort(Direction.ASC, "school").and(new Sort(Sort.Direction.ASC, "major")).and(new Sort(Sort.Direction.DESC, "zongfen"));
		return luQuDAO.findAll(spec, s);
	}

	@Transactional(readOnly = true)
	public List<BatchLineVO> getBatchLineList() {
		Iterator<BatchLineVO> iter = this.batchLineDAO.findAll().iterator();
		List<BatchLineVO> batchLineList = new ArrayList<BatchLineVO>();
		while (iter.hasNext()) {
			batchLineList.add(iter.next());
		}
		return batchLineList;
	}

	@Transactional(readOnly = true)
	public List<BatchLineVO> getBatchLine(Integer year, String type) {
		return this.batchLineDAO.getBatchLine(year, type.toString());
	}

	@Override
	public List<TiMuVO> getTiMuList() {
		List<TiMuVO> vos = new ArrayList<TiMuVO>();
		Iterator<TiMuVO> iter = this.tiMuDAO.findAll().iterator();
		while (iter.hasNext()) {
			TiMuVO vo = iter.next();
			vos.add(vo);
		}
		return vos;
	}

	@Override
	public DaAnVO getDaAn(String value) {
		return this.daAnDAO.findOne(value);
	}

	@Transactional(readOnly = true)
	public List<LuQuVO> getLuquXinxiAllYear(ParamVO paramVO) {
		List<LuQuVO> vos = new ArrayList<LuQuVO> ();
		String sql = builderSql(paramVO);
		System.out.println(sql);
		Connection conn = null;
		try {
			Class.forName("com.mysql.jdbc.Driver");
			Configuration props = ResourceUtil.loadProps("jdbc.properties");
			String connectStr = props.getString("jdbc.url") + "&user=" +props.getString("jdbc.username") + "&password=" + props.getString("jdbc.password");
			conn = DriverManager.getConnection(connectStr);
			PreparedStatement psts = conn.prepareStatement(sql);
			ResultSet rs = psts.executeQuery();
			while (rs.next()) {
				int college_id = rs.getInt("college_id");
				String school = rs.getString("school");
				String major_id = rs.getString("major_id");
				String major = rs.getString("major");
				String batch = rs.getString("batch");
				int year = rs.getInt("year");
				LuQuVO vo = new LuQuVO();
				vo.setCollege_id(college_id);
				vo.setSchool(school);
				vo.setMajor_id(major_id);
				vo.setMajor(major);
				vo.setBatch(batch);
				vo.setYear(year);
				vos.add(vo);
			}
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			try {
				conn.close();
			} catch (SQLException e) {
			}
		}
		return vos;
		
	}

	private String builderSql(ParamVO paramVO) {
		StringBuilder sb = new StringBuilder();
		this.setMaxMinScore(paramVO, 2014);
		sb.append("select college_id, school, major_id, major, batch, year from luquxinxi where zongfen between ");
		sb.append(paramVO.getMinScore()).append(" and ").append(paramVO.getMaxScore());
		sb.append(" and year=2014");
		if (StringUtils.isNotBlank(paramVO.getBatch())) {
			sb.append(" and batch='").append(paramVO.getBatch()).append("'");
		}
		if (StringUtils.isNotBlank(paramVO.getEnroll())) {
			sb.append(" and enroll='").append(paramVO.getEnroll()).append("'");
		}
		if (StringUtils.isNotBlank(paramVO.getPlan())) {
			sb.append(" and plan='").append(paramVO.getPlan()).append("'");
		}
		if (StringUtils.isNotBlank(paramVO.getType())) {
			sb.append(" and type='").append(paramVO.getType()).append("'");
		}
		if (StringUtils.isNotBlank(paramVO.getSchool())) {
			sb.append(" and school like '%").append(paramVO.getSchool()).append("%'");
		}
		if (StringUtils.isNotBlank(paramVO.getMajor())) {
			sb.append(" and major like '%").append(paramVO.getMajor()).append("%'");
		}
		
		sb.append(" union all ");
		
		this.setMaxMinScore(paramVO, 2013);
		sb.append("select college_id, school, major_id, major, batch, year from luquxinxi where zongfen between ");
		sb.append(paramVO.getMinScore()).append(" and ").append(paramVO.getMaxScore());
		sb.append(" and year=2013");
		if (StringUtils.isNotBlank(paramVO.getBatch())) {
			sb.append(" and batch='").append(paramVO.getBatch()).append("'");
		}
		if (StringUtils.isNotBlank(paramVO.getEnroll())) {
			sb.append(" and enroll='").append(paramVO.getEnroll()).append("'");
		}
		if (StringUtils.isNotBlank(paramVO.getPlan())) {
			sb.append(" and plan='").append(paramVO.getPlan()).append("'");
		}
		if (StringUtils.isNotBlank(paramVO.getType())) {
			sb.append(" and type='").append(paramVO.getType()).append("'");
		}
		if (StringUtils.isNotBlank(paramVO.getSchool())) {
			sb.append(" and school like '%").append(paramVO.getSchool()).append("%'");
		}
		if (StringUtils.isNotBlank(paramVO.getMajor())) {
			sb.append(" and major like '%").append(paramVO.getMajor()).append("%'");
		}

		sb.append(" union all ");
		
		this.setMaxMinScore(paramVO, 2012);
		sb.append("select college_id, school, major_id, major, batch, year from luquxinxi where zongfen between ");
		sb.append(paramVO.getMinScore()).append(" and ").append(paramVO.getMaxScore());
		sb.append(" and year=2012");
		if (StringUtils.isNotBlank(paramVO.getBatch())) {
			sb.append(" and batch='").append(paramVO.getBatch()).append("'");
		}
		if (StringUtils.isNotBlank(paramVO.getEnroll())) {
			sb.append(" and enroll='").append(paramVO.getEnroll()).append("'");
		}
		if (StringUtils.isNotBlank(paramVO.getPlan())) {
			sb.append(" and plan='").append(paramVO.getPlan()).append("'");
		}
		if (StringUtils.isNotBlank(paramVO.getType())) {
			sb.append(" and type='").append(paramVO.getType()).append("'");
		}
		if (StringUtils.isNotBlank(paramVO.getSchool())) {
			sb.append(" and school like '%").append(paramVO.getSchool()).append("%'");
		}
		if (StringUtils.isNotBlank(paramVO.getMajor())) {
			sb.append(" and major like '%").append(paramVO.getMajor()).append("%'");
		}

		sb.append(" union all ");
		
		this.setMaxMinScore(paramVO, 2011);
		sb.append("select college_id, school, major_id, major, batch, year from luquxinxi where zongfen between ");
		sb.append(paramVO.getMinScore()).append(" and ").append(paramVO.getMaxScore());
		sb.append(" and year=2011");
		if (StringUtils.isNotBlank(paramVO.getBatch())) {
			sb.append(" and batch='").append(paramVO.getBatch()).append("'");
		}
		if (StringUtils.isNotBlank(paramVO.getEnroll())) {
			sb.append(" and enroll='").append(paramVO.getEnroll()).append("'");
		}
		if (StringUtils.isNotBlank(paramVO.getPlan())) {
			sb.append(" and plan='").append(paramVO.getPlan()).append("'");
		}
		if (StringUtils.isNotBlank(paramVO.getType())) {
			sb.append(" and type='").append(paramVO.getType()).append("'");
		}
		if (StringUtils.isNotBlank(paramVO.getSchool())) {
			sb.append(" and school like '%").append(paramVO.getSchool()).append("%'");
		}
		if (StringUtils.isNotBlank(paramVO.getMajor())) {
			sb.append(" and major like '%").append(paramVO.getMajor()).append("%'");
		}

		sb.append(" union all ");
		
		this.setMaxMinScore(paramVO, 2010);
		sb.append("select college_id, school, major_id, major, batch, year from luquxinxi where zongfen between ");
		sb.append(paramVO.getMinScore()).append(" and ").append(paramVO.getMaxScore());
		sb.append(" and year=2010");
		if (StringUtils.isNotBlank(paramVO.getBatch())) {
			sb.append(" and batch='").append(paramVO.getBatch()).append("'");
		}
		if (StringUtils.isNotBlank(paramVO.getEnroll())) {
			sb.append(" and enroll='").append(paramVO.getEnroll()).append("'");
		}
		if (StringUtils.isNotBlank(paramVO.getPlan())) {
			sb.append(" and plan='").append(paramVO.getPlan()).append("'");
		}
		if (StringUtils.isNotBlank(paramVO.getType())) {
			sb.append(" and type='").append(paramVO.getType()).append("'");
		}
		if (StringUtils.isNotBlank(paramVO.getSchool())) {
			sb.append(" and school like '%").append(paramVO.getSchool()).append("%'");
		}
		if (StringUtils.isNotBlank(paramVO.getMajor())) {
			sb.append(" and major like '%").append(paramVO.getMajor()).append("%'");
		}
		return sb.toString();
	}
	
	private void setMaxMinScore(ParamVO paramVO, Integer year) {
		
		List<BatchLineVO> batchList = this.batchLineDAO.getBatchLine(2015, paramVO.getType());
		BatchLineVO VO2015 = null;
		for (BatchLineVO vo : batchList) {
			if (vo.getScore() > paramVO.getScore())
				break;
			VO2015 = vo;
		}
		
		paramVO.setBatchLineVO(VO2015);
		
		if (paramVO.getAlgorithm().equalsIgnoreCase("线差法")) {
			Double value = paramVO.getScore() - VO2015.getScore();
			
			batchList = this.batchLineDAO.getBatchLine(year, paramVO.getType());
			BatchLineVO findVO = null;
			for (BatchLineVO vo : batchList) {
				if (vo.getBatch().equals(VO2015.getBatch())
						&& vo.getClazz().equals(VO2015.getClazz())) {
					findVO = vo;
					break;
				}
			}
			
			Double max_score = findVO.getScore() + value + paramVO.getUp();
			Double min_score = findVO.getScore() + value - paramVO.getDown();
			Double score = findVO.getScore() + value;
			EntityScoreVO entity = new EntityScoreVO();
			
			entity.setMax_score(max_score);
			entity.setMin_score(min_score);
			entity.setScore(score);
			entity.setYear(year);
			paramVO.addEntity(entity);
			
			paramVO.setMaxScore(max_score);
			paramVO.setMinScore(min_score);
		} else if (paramVO.getAlgorithm().equals("位次法")) {
			Integer score = paramVO.getScore().intValue();
			String subject = paramVO.getType();
			//查询15年的位次
			ScoreVO ranking = this.scoreDAO.findOne(2015, score, subject);
			//使用15的位次查询当年的分数
			ScoreVO _ranking = this.scoreDAO.queryRankingByRanking(year, ranking.getRanking(), subject);
			Double max_score = (double) (_ranking.getScore() + paramVO.getUp());
			Double min_score = (double) (_ranking.getScore() - paramVO.getDown());
			
			EntityScoreVO entity = new EntityScoreVO();
			
			entity.setMax_score(max_score);
			entity.setMin_score(min_score);
			entity.setScore(_ranking.getScore().doubleValue());
			entity.setYear(year);
			paramVO.addEntity(entity);
			
			paramVO.setMaxScore(max_score);
			paramVO.setMinScore(min_score);
		}
	}

	@Override
	public Map<Integer, CollegeVO> getCollegeBaseMap() {
		Iterator<CollegeVO> iter = this.collegeDAO.findAll().iterator();
		Map<Integer, CollegeVO> maps = new HashMap<Integer, CollegeVO> ();
		while (iter.hasNext()) {
			CollegeVO vo = iter.next();
			maps.put(vo.getCollege_id(), vo);
		}
		return maps;
	}

	@Override
	public Map<Integer, MajorVO> getMajorBaseMap() {
		Iterator<MajorVO> iter = this.majorDAO.findAll().iterator();
		Map<Integer, MajorVO> maps = new HashMap<Integer, MajorVO> ();
		while (iter.hasNext()) {
			MajorVO vo = iter.next();
			maps.put(vo.getMajor_id(), vo);
		}
		return maps;
	}

	@Autowired
	IMajorEnrollDAO majorEnrollDAO;
	
	@Override
	public List<MajorEnrollVO> getMajorEnrollList(Integer college_id,
			String major_id, String batch, String subject) {
		return this.majorEnrollDAO.getMajorEnrollList(college_id,
				major_id, subject);
	}
	@Autowired
	IScoreDAO scoreDAO;

	@Override
	public ScoreVO getRankingByRanking(Integer year, String subject,
			Integer ranking) {
		return this.scoreDAO.queryRankingByRanking(year, ranking, subject);
	}

	@Override
	public ScoreVO getRanking(int year, String subject, Integer score) {
		return this.scoreDAO.findOne(year, score, subject);
	}

	@Override
	public List<MajorEnrollVO> getMajorEnrollListByParamVO(ParamVO paramVO) {
		List<SearchFilter> searchFilterList = new ArrayList<SearchFilter>();
		String batch = paramVO.getBatch();
		String region = paramVO.getRegion();
		String type = paramVO.getType();
		Integer year = paramVO.getYear();
		Integer college_id = paramVO.getCollege_id();
		Integer major_id = paramVO.getMajor_id();

		SearchFilter filter = null;

		if (year != null && year != 0) {
			filter = new SearchFilter("year", Operator.EQ, year, null);
			searchFilterList.add(filter);
		}
		
		if (StringUtils.isNoneBlank(region)) {
			filter = new SearchFilter("region", Operator.EQ, region, null);
			searchFilterList.add(filter);
		}

		if (StringUtils.isNotBlank(type)) {
			filter = new SearchFilter("subject", Operator.EQ, type, null);
			searchFilterList.add(filter);
		}

		if (StringUtils.isNotBlank(batch)) {
			filter = new SearchFilter("batch", Operator.EQ, batch, null);
			searchFilterList.add(filter);
		}

		if (college_id != null) {
			filter = new SearchFilter("college_id", Operator.EQ, college_id, null);
			searchFilterList.add(filter);
		}

		if (major_id != null) {
			filter = new SearchFilter("major_id", Operator.EQ,
					major_id, null);
			searchFilterList.add(filter);
		}
		Specification<MajorEnrollVO> spec = DynamicSpecifications.bySearchFilter(
				searchFilterList, MajorEnrollVO.class);
//		Sort s = new Sort(Direction.ASC, "college_id").and(new Sort(Sort.Direction.ASC, "major_id")).and(new Sort(Sort.Direction.DESC, "avg_score"));
		return majorEnrollDAO.findAll(spec);
//		return majorEnrollDAO.findAll(spec, s);
	}
	
	static HttpClient client = new HttpClient();
	
	@Autowired
	ISchool2DAO school2DAO;
	
	static Set<String> clazz_set = new HashSet<String> ();
	static {
		clazz_set.add("普通文科");
		clazz_set.add("普通理科");
		clazz_set.add("蒙授理科");
		clazz_set.add("蒙授文科");
	}
	public static String time_desc = null;
	
	public void parserHome(String url) throws HttpException, IOException {
		GetMethod post = new GetMethod(url);
		post.setRequestHeader("Connection", "Keep-Alive");
		post.setRequestHeader("Referer",
				"http://www.nm.zsks.cn/zy_1_1_2015/kl_10.html");
		post.setRequestHeader(
				"User-Agent",
				"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.124 Safari/537.36");
		post.setRequestHeader("Accept-Language", "zh-CN,zh;q=0.8");
		post.setRequestHeader("Origin", "http://gaokao.chsi.com.cn");
		post.setRequestHeader("Accept",
				"text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8");

		int code = client.executeMethod(post);
		if (code != 200) {
			System.out.println("error response code=" + code);
		}

		byte[] b = post.getResponseBody();
		Document doc = Jsoup.parse(new ByteArrayInputStream(b), "gbk",
				"http://www.nm.zsks.cn/zy_1_1_2015/");
		
		Elements trs = doc.select("tr[style=height:110px;");
		if (trs != null && !trs.isEmpty()) {
			Elements tds = trs.get(0).select("td[class=report1_1_2]");
			if (tds != null && !tds.isEmpty())
				UserFacade.time_desc = tds.get(0).text(); 
		}
		Elements links = doc.select("a[href]"); // 带有href属性的a元素
		for (Element link : links) {
			String text = link.text().trim();
			if (!clazz_set.contains(text))
				continue;
			String href = "http://www.nm.zsks.cn" + link.attr("href");
			parserClazz(href, text);
		}

	}

	private void parserSchool(byte[] b, String clazz) throws IOException, HttpException {
		Document doc = Jsoup.parse(new ByteArrayInputStream(b), "gbk",
				"http://www.nm.zsks.cn/zy_1_1_2015/");
		Elements trs = doc.select("tr[style=height:22px;]");
		Elements headLine = doc.select("tr[style=height:32px;]").select("td");
		ArrayList<SchoolVO2> schools = new ArrayList<SchoolVO2>();
		for (int i = 0; i < trs.size(); i++) {
			if (i == 0)
				continue;
			Element tr = trs.get(i);
			Elements tds = tr.select("td");
			SchoolVO2 schoolVO = parserSchoolVO(tds, headLine);
			schoolVO.setClazz(clazz);
			schools.add(schoolVO);
			parserMajor(schoolVO, clazz);
			if (schoolVO.getYibaorenshu() > 0)
				parserStudent(schoolVO, clazz);
			this.school2DAO.save(schoolVO);
		}
		

	}

	private void parserStudent(SchoolVO2 schoolVO, String clazz)
			throws HttpException, IOException {
		GetMethod post = new GetMethod(schoolVO.getStudent_href());
		post.setRequestHeader("Connection", "Keep-Alive");
		post.setRequestHeader("Referer",
				"http://www.nm.zsks.cn/zy_1_1_2015/kl_10.html");
		post.setRequestHeader(
				"User-Agent",
				"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.124 Safari/537.36");
		post.setRequestHeader("Accept-Language", "zh-CN,zh;q=0.8");
		post.setRequestHeader("Origin", "http://gaokao.chsi.com.cn");
		post.setRequestHeader("Accept",
				"text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8");

		int code = client.executeMethod(post);
		if (code != 200) {
			System.out.println("error response code=" + code);
		}

		byte[] b = post.getResponseBody();
		List<RealtimeStudentVO> students = parserStudentVO(new ByteArrayInputStream(b), schoolVO);
		schoolVO.setStudents(students);
	}

	private List<RealtimeStudentVO> parserStudentVO(InputStream input, SchoolVO2 school)
			throws IOException {
		Document doc = Jsoup.parse(input, "gbk",
				"http://www.nm.zsks.cn/zy_1_1_2015/");
		Elements trs = doc.select("tr");
		List<RealtimeStudentVO> vos = new ArrayList<RealtimeStudentVO>();
		for (int i = 0; i < trs.size(); i++) {
			Element tr = trs.get(i);
			Elements tds = tr.select("td");
			if (tds.size() == 0 || tds.size() != 11)
				continue;
			if (tds.get(0).text().equals("投档分 （含照顾分）"))
				continue;
			RealtimeStudentVO vo = new RealtimeStudentVO();
			int j = 0;
			List<String> major = new ArrayList<String> ();
			for (Element td : tds) {
				if (j == 0) {
					vo.setApply_score(Integer.valueOf(td.text()));
				} else if (j == 1) {
					vo.setTest_score(Integer.valueOf(td.text()));
				} else if (j == 2) {
					vo.setNation(td.text());
				} else if (j == 3) {
					vo.setGendar(td.text());
				} else if (j == 4) {
					if (!StringUtil.isBlank(td.text()))
						major.add(td.text());
				} else if (j == 5) {
					if (!StringUtil.isBlank(td.text()))
						major.add(td.text());
				} else if (j == 6) {
					if (!StringUtil.isBlank(td.text()))
						major.add(td.text());
				} else if (j == 7) {
					if (!StringUtil.isBlank(td.text()))
						major.add(td.text());
				} else if (j == 8) {
					if (!StringUtil.isBlank(td.text()))
						major.add(td.text());
				} else if (j == 9) {
					if (!StringUtil.isBlank(td.text()))
						major.add(td.text());
				} else if (j == 10) {
					if (td.text().equals("是")) {
						vo.setObey(true);
					} else {
						vo.setObey(false);
					}
				}
				j++;
			}
			vo.setClazz(school.getClazz());
			vo.setMajor(major);
			vo.setSchool(school);
			vos.add(vo);
		}
		return vos;
	}

	private void parserMajor(SchoolVO2 schoolVO, String clazz)
			throws HttpException, IOException {
		GetMethod post = new GetMethod(schoolVO.getSchool_href());
		post.setRequestHeader("Connection", "Keep-Alive");
		post.setRequestHeader("Referer",
				"http://www.nm.zsks.cn/zy_1_1_2015/kl_10.html");
		post.setRequestHeader(
				"User-Agent",
				"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.124 Safari/537.36");
		post.setRequestHeader("Accept-Language", "zh-CN,zh;q=0.8");
		post.setRequestHeader("Origin", "http://gaokao.chsi.com.cn");
		post.setRequestHeader("Accept",
				"text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8");

		int code = client.executeMethod(post);
		if (code != 200) {
			System.out.println("error response code=" + code);
		}

		byte[] b = post.getResponseBody();
		List<MajorVO2> majors = parserMajorVO(new ByteArrayInputStream(b), schoolVO);
		schoolVO.setMajors(majors);
	}

	private List<MajorVO2> parserMajorVO(InputStream input, SchoolVO2 school)
			throws IOException {
		Document doc = Jsoup.parse(input, "gbk",
				"http://www.nm.zsks.cn/zy_1_1_2015/");
		Elements trs = doc.select("tr");
		List<MajorVO2> majors = new ArrayList<MajorVO2>();
		for (int i = 0; i < trs.size(); i++) {
			Element tr = trs.get(i);
			Elements tds = tr.select("td");
			if (tds.size() == 0 || tds.size() != 8)
				continue;
			if (tds.get(0).text().equals("专业代号"))
				continue;
			if (tds.get(6).text().equals("统计时间："))
				continue;
			MajorVO2 vo = new MajorVO2();
			int j = 0;
			for (Element td : tds) {
				if (j == 0) {
					vo.setMajor_id(td.text());
				} else if (j == 1) {
					vo.setMajor_name(td.text());
				} else if (j == 2) {
					vo.setPlan_num(Integer.valueOf(td.text()));
				} else if (j == 3) {
					vo.setYuji1bi1luquzuidifen(Integer.valueOf(td.text()));
				} else if (j == 4) {
					vo.setApply_num(Integer.valueOf(td.text()));
				} else if (j == 5) {
					vo.setXuefei(td.text());
				} else if (j == 6) {
					vo.setLocation(td.text());
				} else if (j == 7) {
					vo.setRemark(td.text());
				}
				j++;
			}
			vo.setSchoolVO2(school);
			majors.add(vo);
		}
		return majors;
	}

	private SchoolVO2 parserSchoolVO(Elements tds, Elements headLine) {
		if (tds.size() < 8)
			return null;
		SchoolVO2 vo = null;
		String school_id = null;
		String school_name = null;
		Integer plan_num = null;
		Integer yuji1bi1toudangzuidifen = null;
		String toudangbili = null;
		Integer yujitoudangzuidifen = null;
		Integer yingtoudangrenshu = null;
		Integer yibaorenshu = null;
		Integer quedangrenshu = null;
		String school_href = null;
		String student_href = null;
		for (int i = 0; i < headLine.size(); i++) {
			String head = headLine.get(i).text();
			Element td = tds.get(i);
			if (head.matches("院\\s?校\\s?代\\s?号\\s?")) {
				school_id = td.text();
			} else if (head.matches("院\\s?校\\s?名\\s?称\\s?")) {
				school_name = td.text();
				school_href = "http://www.nm.zsks.cn"
						+ td.getElementsByTag("a").get(0).attr("href");
			} else if (head.matches("计\\s?划\\s?数\\s?")) {
				plan_num = Integer.valueOf(td.text());
			} else if (head.indexOf("1:1") != -1) {
				yuji1bi1toudangzuidifen = Integer.valueOf(td.text());
			} else if (head.matches("投\\s?档\\s?比\\s?例\\s?")) {
				toudangbili = td.text();
			} else if (head.matches("预\\s?计\\s?投\\s?档\\s?最\\s?低\\s?分\\s?")) {
				yujitoudangzuidifen = Integer.valueOf(td.text());
			} else if (head.matches("应\\s?投\\s?档\\s?人\\s?数\\s?")) {
				yingtoudangrenshu = Integer.valueOf(td.text());
			} else if (head.matches("已\\s?报\\s?人\\s?数\\s?")) {
				yibaorenshu = Integer.valueOf(td.text());
				student_href = "http://www.nm.zsks.cn"
						+ td.getElementsByTag("a").get(0).attr("href");
			} else if (head.matches("缺\\s?档\\s?人\\s?数\\s?")) {
				if (!StringUtil.isBlank(td.text()))
					quedangrenshu = Integer.valueOf(td.text());
			}
		}
		vo = new SchoolVO2();
		vo.setPlan_num(plan_num);
		vo.setQuedangrenshu(quedangrenshu);
		vo.setSchool_href(school_href);
		vo.setSchool_id(school_id);
		vo.setSchool_name(school_name);
		vo.setStudent_href(student_href);
		vo.setToudangbili(toudangbili);
		vo.setYibaorenshu(yibaorenshu);
		vo.setYingtoudangrenshu(yingtoudangrenshu);
		vo.setYuji1bi1toudangzuidifen(yuji1bi1toudangzuidifen);
		vo.setYujitoudangzuidifen(yujitoudangzuidifen);
		return vo;
	}

	private void parserClazz(String href, String clazz)
			throws HttpException, IOException {
		GetMethod post = new GetMethod(href);
		post.setRequestHeader("Connection", "Keep-Alive");
		post.setRequestHeader("Referer",
				"http://www.nm.zsks.cn/zy_1_1_2015/kl_10.html");
		post.setRequestHeader(
				"User-Agent",
				"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.124 Safari/537.36");
		post.setRequestHeader("Accept-Language", "zh-CN,zh;q=0.8");
		post.setRequestHeader("Origin", "http://gaokao.chsi.com.cn");
		post.setRequestHeader("Accept",
				"text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8");

		int code = client.executeMethod(post);
		if (code != 200) {
			System.out.println("error response code=" + code);
		}

		
		byte[] b = post.getResponseBody();
		parserSchool(b, clazz);
	}

	@Transactional(readOnly = false)
	public void deleteRealtimeAll() {
		this.school2DAO.deleteAll();
	}

	@Override
	public List<SchoolVO2> getRealtimeAll() {
		List<SchoolVO2> schools = new ArrayList<SchoolVO2> ();
		Iterator<SchoolVO2> iter = this.school2DAO.findAll().iterator();
		while (iter.hasNext()) {
			schools.add(iter.next());
		}
		return schools;
	}

	@Override
	public List<String> getAllSchoolName() {
		return this.school2DAO.findAllSchoolName();
	}

	@Override
	public SchoolVO2 getSchoolVO(String school_id, String school_name, String clazz) {
		return this.school2DAO.findSchoolVO(school_id, school_name, clazz);
	}

	@Override
	public List<SchoolVO2> getSchoolList(String clazz, Integer sort) {
		List<SearchFilter> searchFilterList = new ArrayList<SearchFilter>();

		SearchFilter filter = new SearchFilter("clazz", Operator.EQ, clazz, null);
		searchFilterList.add(filter);
		
		Specification<SchoolVO2> spec = DynamicSpecifications.bySearchFilter(
				searchFilterList, SchoolVO2.class);
		Sort s = null;
		if (sort == 1) {
			s = new Sort(Direction.DESC, "yuji1bi1toudangzuidifen");
		} else {
			s = new Sort(Direction.DESC, "yujitoudangzuidifen");
		}
		return this.school2DAO.findAll(spec, s);
	}
	
	@Autowired
	IRealtimeStudentDAO studentDAO;

	@Override
	public List<RealtimeStudentVO> getStudentList(String clazz, Integer max_score,
			Integer min_score) {
		return this.studentDAO.findSchoolVO(clazz, max_score, min_score);
	}

	@Override
	public UserVO findUserByMobile(String mobile) {
		return userDAO.findByMobile(mobile);
	}

	@Transactional(readOnly = false)
	public void updateMobile(String mobile, Long userId) {
		this.userDAO.updateMobile(mobile, userId);
	}

	@Override
	public ResetTokenVO queryResetToken(String email) {
		return resetTokenDAO.findByEmail(email);
	}

	@Transactional(readOnly = false)
	public void deleteAllResetToken(String email) {
		this.resetTokenDAO.deleteByEmail(email);
	}

	@Transactional(readOnly = false)
	public String createNewToken(String email) {
		//先删除旧的token信息
		this.resetTokenDAO.deleteByEmail(email);
		//创建新的
		String id = NumSequenceUtil.getUUID();
		ResetTokenVO token = new ResetTokenVO();
		token.setId(id);
		token.setEmail(email);
		token.setSendDate(new Date());
		token.setStatus(0);
		this.resetTokenDAO.save(token);
		return id;
	}

	@Transactional(readOnly = false)
	public ResetTokenVO findTokenById(String id) {
		return this.resetTokenDAO.findOne(id);
	}

	@Transactional(readOnly = false)
	public void resetPwd(ResetTokenVO token, String pwd) {
		this.userDAO.resetPwd(token.getEmail(), MD5Util.md5(pwd+token.getEmail()));
		this.resetTokenDAO.delete(token.getId());
	}

	@Override
	public List<MenuVO> getUserMenu(List<Long> roleIdList) {
		return this.menuDao.findMenuByRoleIdList(roleIdList);
	}

}
